/**
 * Copyright (c) 2015-2017, Henry Yang 杨勇 (gismail@foxmail.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lambkit.module.cms.rpc.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.FileUtils;

import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.lambkit.common.service.LambkitModelServiceImpl;
import com.lambkit.common.util.DateTimeUtils;
import com.lambkit.core.aop.AopKit;
import com.lambkit.module.cms.Cms;
import com.lambkit.module.cms.core.km.CompressUtil;
import com.lambkit.module.cms.core.km.FileStateEnum;
import com.lambkit.module.cms.core.km.JudgeUtils;
import com.lambkit.module.cms.core.km.Km;
import com.lambkit.module.cms.core.km.ThumbnailUtils;
import com.lambkit.module.cms.core.km.TranslateUtils;
import com.lambkit.module.cms.core.search.SearcherKit;
import com.lambkit.module.cms.rpc.api.CmsFileService;
import com.lambkit.module.cms.rpc.model.CmsArticle;
import com.lambkit.module.cms.rpc.model.CmsCategory;
import com.lambkit.module.cms.rpc.model.CmsFile;
import com.lambkit.module.cms.rpc.model.CmsMessage;
import com.lambkit.module.cms.rpc.model.CmsRelation;
import com.lambkit.module.cms.rpc.model.CmsTag;
import com.lambkit.module.upms.rpc.model.UpmsUser;

/**
 * @author yangyong 
 * @website: www.lambkit.com
 * @email: gismail@foxmail.com
 * @date 2020-02-23
 * @version 1.0
 * @since 1.0
 */
public class CmsFileServiceImpl extends LambkitModelServiceImpl<CmsFile> implements CmsFileService {
	
	private CmsFile DAO = null;
	
	public CmsFile dao() {
		if(DAO==null) {
			DAO = AopKit.singleton(CmsFile.class);
		}
		return DAO;
	}
	

	@Override
	public int insertFile(CmsFile fileInfo) {
		// TODO Auto-generated method stub
		boolean flag = fileInfo.save();
		return flag ? 1 : 0;
	}

	@Override
	public List<String> compressFile(String name, Long userid) throws Exception {
		// TODO Auto-generated method stub
		List<String> uuids = new ArrayList<String>();
		List<CmsFile> files = CompressUtil.startCompress(name, userid);
		try {
			FileUtils.forceDelete(new File(name));
		} catch (Exception e) {
			//LOG.error("删除文件失败" + name);
		}
		for (CmsFile f : files) {
			f.setFileUserId(userid);
			f.setFileCategoryId(1L);
			f.setFileBrief("");
			f.save();
			uuids.add(f.getFileUuid());
		}
		return uuids;
	}

	@Override
	public void translateFile(String uuid) throws IOException {
		// TODO Auto-generated method stub
		// 设置文件问后台处理中
		setFileStateByUuid(uuid, 3);
		CmsFile file = getByUuid(uuid);
		//LOG.debug("开始转化文件" + uuid);
		if (JudgeUtils.isOfficeFile(file.getFileExt())) {
			// 文档转化
			if (!file.getFileExt().equals("pdf")) {
				Km.officeConvert().convertToPDF(new File(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt()),
						new File(Cms.config().getFilePath() + file.getFilePath() + ".pdf"));
			}
			// 获取pdf缩略图 路径为 + Cms.config().getFilePath() + file.getFilePath()+".png"
			if (new File(Cms.config().getFilePath() + file.getFilePath() + ".pdf").exists()) {
				ThumbnailUtils.pdfGetThumb(Cms.config().getFilePath() + file.getFilePath() + ".pdf",
						Cms.config().getFilePath() + file.getFilePath() + ".png");
			} else {
				setFileStateByUuid(uuid, 1);
				return;
			}
		} else if (JudgeUtils.isVideoFile(file.getFileExt())) {

			if (file.getFileExt().equals("flv")) {
				try {
					FileUtils.copyFile(new File(Cms.config().getFilePath() + "defaultfile/flv.png"),
							new File(Cms.config().getFilePath() + file.getFilePath() + ".png"));
				} catch (Exception e) {
					//LOG.error("flv默认图标不存在");
				}
				FileUtils.copyFile(new File(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt()),
						new File(Cms.config().getStreamPath() + file.getFileUuid() + ".flv"));
			} else if (file.getFileExt().equals("mp4")) {

				ThumbnailUtils.videoGetThumb(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt(),
						Cms.config().getFilePath() + file.getFilePath() + ".png");

				FileUtils.copyFile(new File(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt()),
						new File(Cms.config().getStreamPath() + file.getFileUuid() + "." + file.getFileExt()));
			} else {

				ThumbnailUtils.videoGetThumb(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt(),
						Cms.config().getFilePath() + file.getFilePath() + ".png");
				// ffmpeg转换成flv
				TranslateUtils.processFLV(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt(),
						Cms.config().getStreamPath() + file.getFileUuid() + ".flv");
			}

		} else if (JudgeUtils.isImageFile(file.getFileExt())) {

			TranslateUtils.toPNG(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt(),
					Cms.config().getFilePath() + file.getFilePath() + ".png");

		} else if (JudgeUtils.isAudioFile(file.getFileExt())) {
			try {
				FileUtils.copyFile(new File(Cms.config().getFilePath() + "defaultfile/mp3.png"),
						new File(Cms.config().getFilePath() + file.getFilePath() + ".png"));
			} catch (Exception e) {
				//LOG.error("mp3默认图标不存在");
			}
			// ffmpeg转换成flv
			TranslateUtils.processFLV(Cms.config().getFilePath() + file.getFilePath() + "." + file.getFileExt(),
					Cms.config().getStreamPath() + file.getFileUuid() + ".flv");
		} else {
			File filetemp = new File(Cms.config().getFilePath() + "defaultfile/" + file.getFileExt() + ".png");
			if (filetemp.exists()) {
				FileUtils.copyFile(new File(Cms.config().getFilePath() + "defaultfile/" + file.getFileExt() + ".png"),
						new File(Cms.config().getFilePath() + file.getFilePath() + ".png"));
			} else {
				try {
					FileUtils.copyFile(new File(Cms.config().getFilePath() + "defaultfile/question.png"),
							new File(Cms.config().getFilePath() + file.getFilePath() + ".png"));
				} catch (Exception e) {
					//LOG.error("?默认图标不存在");
				}
			}

		}
		// 修改文件为私有可以查看
		// setFileStateByUuid(uuid, 6);
		file.setFileState(6);
		CmsMessage msg = new CmsMessage(null, "文件上传成功", "您的文件：“" + file.getFileName() + "”上传成功", file.getFileUserId(),
				false, new Date());
		msg.save();
		// 创建索引
		UpmsUser user = UpmsUser.service().findById(file.getFileUserId());
		String userName = user!=null ? user.getUsername() : null;
		SearcherKit.fileSearcher().addFileIndex(file, userName, null);
		if (file.getFileBrief() == null || file.getFileBrief().equals("")) {
			String text = SearcherKit.fileSearcher().getSummary(file, 3L);
			file.setFileBrief(text);
		}
		updateByUuid(file);
	}

	public int updateByUuid(CmsFile file) {
		// TODO Auto-generated method stub
		boolean flag = file.update();
		return flag ? 1 : 0;
		//return update(file.toRecord(), CmsFile.sql().andFileUuidEqualTo(file.getFileUuid()).example());
	}

	public void setFileStateByUuid(String uuid, int i) {
		// TODO Auto-generated method stub
		SqlPara sqlPara = Db.getSqlPara("cms.file_setFileStateByUuid", i, uuid);
		Cms.db().update(sqlPara);
	}

	@Override
	public CmsFile getByUuid(String uuid) {
		// TODO Auto-generated method stub
		SqlPara sqlPara = Db.getSqlPara("cms.file_findByUuid", uuid);
		return dao().findFirst(sqlPara);
	}
	
	@Override
	public CmsFile getByFileId(Long fileId) {
		// TODO Auto-generated method stub
		return findById(fileId);
	}

	@Override
	public int saveByUuid(CmsFile fileInfo) {
		// TODO Auto-generated method stub
		return updateByUuid(fileInfo);
	}

	@Override
	public Page<CmsFile> searchByNameOrId(String searchInfo, Long userId, Integer pageNo, int pageSize) {
		// TODO Auto-generated method stub
		SqlPara sqlPara = Db.getSqlPara("cms.file_searchByNameOrId", userId, "%" + searchInfo + "%");
		return dao().paginate(pageNo, pageSize, sqlPara);
	}

	@Override
	public List<CmsFile> searchByNameOrId(String searchInfo, Long userId) {
		// TODO Auto-generated method stub
		SqlPara sqlPara = Db.getSqlPara("cms.file_searchByNameOrId", userId, "%" + searchInfo + "%");
		return dao().find(sqlPara);
	}

	@Override
	public List<CmsRelation> getRelations(Long mainFileId) {
		// TODO Auto-generated method stub
		return CmsRelation.service().findFileList(mainFileId);
	}

	@Override
	public int delRelations(Long mainFileId, Long relationFileId) {
		// TODO Auto-generated method stub
		int rs = CmsRelation.service().delete(
				CmsRelation.sql()
				.andMainTypeEqualTo("file")
				.andMainIdEqualTo(mainFileId)
				.andRelationTypeEqualTo("file")
				.andRelationIdEqualTo(relationFileId)
				.example());
		// 反向也要删除
		CmsRelation.service().delete(
				CmsRelation.sql()
				.andMainTypeEqualTo("file")
				.andMainIdEqualTo(relationFileId)
				.andRelationTypeEqualTo("file")
				.andRelationIdEqualTo(mainFileId)
				.example());
		return rs;
	}

	@Override
	public int delFileById(Long fileId) throws Exception {
		// TODO Auto-generated method stub
		CmsFile fileInfo = getByFileId(fileId);
		// if (fileInfo.getFileState() != 5 && fileInfo.getFileState() != 6 &&
		// fileInfo.getFileState() != 1) {
		// throw new Exception();
		// }
		File file = new File(Cms.config().getFilePath() + fileInfo.getFilePath() + "." + fileInfo.getFileExt());
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}
		file = new File(Cms.config().getFilePath() + fileInfo.getFilePath() + ".png");
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}
		file = new File(Cms.config().getFilePath() + fileInfo.getFilePath() + ".pdf");
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}
		file = new File(Cms.config().getFilePath() + fileInfo.getFilePath() + ".flv");
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}
		file = new File(Cms.config().getStreamPath() + fileInfo.getFileUuid() + ".flv");
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}
		file = new File(Cms.config().getStreamPath() + fileInfo.getFileUuid() + ".mp4");
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}
		return deleteByPrimaryKey(fileId);
	}

	@Override
	public int autoRelation(String uuid) {
		// TODO Auto-generated method stub
		List<CmsRelation> rs = new ArrayList<>();
		CmsRelation r = null;
		CmsFile file = getByUuid(uuid);
		List<Long> list = SearcherKit.fileSearcher().getRelation(file.getFileId());
		for (Long l : list) {
			if (file.getFileId().equals(l)) {
				continue;
			}
			r = new CmsRelation();
			r.setMainId(file.getFileId());
			r.setMainType("file");
			r.setRelationId(l);
			r.setRelationType("file");
			r.setCreateTime(DateTimeUtils.getCurrentTime());
			rs.add(r);

			/*反向也要关联
			r = new CmsRelation();
			r.setMainId(l);
			r.setMainType("file");
			r.setRelationId(file.getFileId());
			r.setRelationType("file");
			r.setCreateTime(DateTimeUtils.getCurrentTime());
			rs.add(r);*/
		}

		int res = 0;
		try {
			res = CmsRelation.service().insertList(rs);
		} catch (Exception e) {
		}
		return res / 2;
	}

	@Override
	public int addRelations(Long mainFileId, List<Long> list) {
		// TODO Auto-generated method stub
		List<CmsRelation> rs = new ArrayList<>();
		CmsRelation r = null;
		for (Long l : list) {
			r = new CmsRelation();
			r.setMainId(mainFileId);
			r.setMainType("file");
			r.setRelationId(l);
			r.setRelationType("file");
			r.setCreateTime(DateTimeUtils.getCurrentTime());
			rs.add(r);

			/* 反向也要关联
			r = new CmsRelation();
			r.setMainId(l);
			r.setMainType("file");
			r.setRelationId(mainFileId);
			r.setRelationType("file");
			r.setCreateTime(DateTimeUtils.getCurrentTime());
			rs.add(r);*/
		}
		int res = 0;
		try {
			res = CmsRelation.service().insertList(rs);
		} catch (Exception e) {
		}
		return res / 2;
	}

	@Override
	public List<CmsFile> getFilesByState(int i) {
		// TODO Auto-generated method stub
		return find(CmsFile.sql().andFileStateEqualTo(i).example());
	}

	@Override
	public void modifyFileExtById(Long fileId, String fileExt) {
		// TODO Auto-generated method stub
		CmsFile f = findById(fileId);
		if(f!=null) {
			f.setFileExt(fileExt);
			f.update();
		}
	}

	@Override
	public Page<CmsFile> getFiles(String searchValue, int pageNo, int pageSize, String order) {
		// TODO Auto-generated method stub
		SqlPara sqlPara = Db.getSqlPara("kms.CmsFile_searchByNameOrId", "%" + searchValue + "%", order);
		return dao().paginate(pageNo, pageSize, sqlPara);
	}
	
	@Override
	public int moveFile(Long cataLogId, Long targetId, String ids) {
		// TODO Auto-generated method stub
		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE ").append("cms_file_category").append(" SET category_id=").append(targetId);
		sql.append(" WHERE file_id in (").append(ids).append(") and category_id=").append(cataLogId);
		return Cms.db().update(sql.toString());
	}

	@Override
	public Page<Record> getPublishByCategory(int pageNumber, int pageSize, Long categoryId, String title, String tags) {
		// TODO Auto-generated method stub
		String path = null;
		if(categoryId==0) {
			path = "0-";
		} else {
			CmsCategory category = CmsCategory.service().findById(categoryId);
			if(category!=null) {
				path = category.getPath();
			}
		}
		if(path == null) return null;
		Kv cond = Kv.by("path", path);
		if(StrKit.notBlank(title)) {
			cond.set("title", title);
		}
		if(StrKit.notBlank(tags)) {
			cond.set("tags", tags);
		}
		SqlPara sqlParaCnt = dao().getSqlPara("cms.km_getPublishByCategory_count", cond);
		List<Record> cnt = Cms.db().find(sqlParaCnt);
		int totalRow = 0;
		for (Record record : cnt) {
			totalRow += record.getInt("cnt");
		}
		int offset = pageSize * (pageNumber - 1);
		cond.set("offset", offset).set("row", pageSize);
		SqlPara sqlPara = dao().getSqlPara("cms.km_getPublishByCategory", cond);
		System.out.println("[getRecentFileAndNote] " + sqlPara.getSql());
		List<Record> list = Cms.db().find(sqlPara);
		Page<Record> page = new Page<>(list, pageNumber, pageSize, totalRow/pageSize, totalRow);
		return page;
	}
	
	@Override
	public Page<Record> getPublishOnCategory(int pageNumber, int pageSize, Long categoryId, String title, String tags) {
		// TODO Auto-generated method stub
		Kv cond = Kv.by("categoryId", categoryId);
		if(StrKit.notBlank(title)) {
			cond.set("title", title);
		}
		if(StrKit.notBlank(tags)) {
			cond.set("tags", tags);
		}
		SqlPara sqlParaCnt = dao().getSqlPara("cms.km_getPublishOnCategory_count", cond);
		List<Record> cnt = Cms.db().find(sqlParaCnt);
		int totalRow = 0;
		for (Record record : cnt) {
			totalRow += record.getInt("cnt");
		}
		int offset = pageSize * (pageNumber - 1);
		cond.set("offset", offset).set("row", pageSize);
		SqlPara sqlPara = dao().getSqlPara("cms.km_getPublishOnCategory", cond);
		System.out.println("[getRecentFileAndNote] " + sqlPara.getSql());
		List<Record> list = Cms.db().find(sqlPara);
		Page<Record> page = new Page<>(list, pageNumber, pageSize, totalRow/pageSize, totalRow);
		return page;
	}

	@Override
	public Page<Record> getRecentFileAndNote(int pageNumber, int pageSize, Long userId) {
		// TODO Auto-generated method stub
		Kv cond = Kv.by("userId", userId);
		SqlPara sqlParaCnt = dao().getSqlPara("cms.km_getRecentFileAndNote_count", cond);
		List<Record> cnt = Cms.db().find(sqlParaCnt);
		int totalRow = 0;
		for (Record record : cnt) {
			totalRow += record.getInt("cnt");
		}
		int offset = pageSize * (pageNumber - 1);
		cond = cond.set("offset", offset).set("row", pageSize);
		SqlPara sqlPara = dao().getSqlPara("cms.km_getRecentFileAndNote", cond);
		System.out.println("[getRecentFileAndNote] " + sqlPara.getSql());
		List<Record> list = Cms.db().find(sqlPara);
		Page<Record> page = new Page<>(list, pageNumber, pageSize, totalRow/pageSize, totalRow);
		return page;
	}

	@Override
	public List<CmsFile> findTagRelevantListByFileId(Long fileId, Integer count) {
		// TODO Auto-generated method stub
		CmsFile file = findById(fileId);
		if(file==null || StrKit.isBlank(file.getFileTag())) {
			return null;
		}
		String tag = file.getFileTag();
		if(tag.startsWith(",")) tag = tag.substring(1);
		if(tag.endsWith(",")) tag = tag.substring(0, tag.length()-1);
		String[] tags = tag.split(",");
        Kv cond = Kv.by("tags", tags).set("status", FileStateEnum.FILE_LOCK);
        SqlPara sqlPara = dao().getSqlPara("cms.file_findRelevantListByTag", cond);
        return dao().find(sqlPara, count);
	}

	@Override
	public List<CmsFile> findListByTagId(Long tagId, String orderBy, Integer count) {
		// TODO Auto-generated method stub
		CmsTag tag = CmsTag.service().findById(tagId);
		if(tag!=null) {
			Kv cond = Kv.by("tagName", tag.getName()).set("orderby", orderBy).set("status", FileStateEnum.FILE_LOCK);
			SqlPara sqlPara = dao().getSqlPara("cms.file_findListByTag", cond);
			return dao().find(sqlPara, count);
		}
		return null;
	}


	@Override
	public Page<CmsFile> paginateByTagId(Integer pageNumber, Integer pageSize, Long tagId) {
		// TODO Auto-generated method stub
		CmsTag tag = CmsTag.service().findById(tagId);
		if(tag!=null) {
			Kv cond = Kv.by("tagName", tag.getName()).set("status", FileStateEnum.FILE_LOCK);
			SqlPara sqlPara = dao().getSqlPara("cms.file_findListByTag", cond);
			return dao().paginate(pageNumber, pageSize, sqlPara);
		}
		return null;
	}


	@Override
	public List<CmsFile> findListByTag(String tag, String orderBy, Integer count) {
		// TODO Auto-generated method stub
		Kv cond = Kv.by("tagName", tag).set("orderby", orderBy).set("status", FileStateEnum.FILE_LOCK);
		SqlPara sqlPara = dao().getSqlPara("cms.findListByTag", cond);
		return dao().find(sqlPara, count);
	}


	@Override
	public Page<CmsFile> paginateByTag(Integer pageNumber, Integer pageSize, String tag) {
		// TODO Auto-generated method stub
		Kv cond = Kv.by("tagName", tag).set("status", CmsArticle.STATUS_NORMAL);
		SqlPara sqlPara = dao().getSqlPara("cms.file_findListByTag", cond);
		return dao().paginate(pageNumber, pageSize, sqlPara);
	}
	
	@Override
	public Page<CmsFile> paginateByUserTag(Integer pageNumber, Integer pageSize, Long userId, String tag) {
		// TODO Auto-generated method stub
		Kv cond = Kv.by("tagName", tag).set("userId", userId).set("status", CmsArticle.STATUS_NORMAL);
		SqlPara sqlPara = dao().getSqlPara("cms.file_findListByTag", cond);
		return dao().paginate(pageNumber, pageSize, sqlPara);
	}

}
